import math
import time

import pandas as pd
import json
import os
from datetime import datetime

import requests
from pandas import ExcelWriter
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side, Color
import pymysql
import akshare as ak
from spiltExcel import capture_excel_sheets_screenshots
from akshare.utils.tqdm import get_tqdm



import matplotlib.pyplot as plt
# 即时资金主力资金流入流出
def stock_individual_fund_flow_rank(indicator: str = "5日") -> pd.DataFrame:
    """
    东方财富网-数据中心-资金流向-排名
    https://data.eastmoney.com/zjlx/detail.html
    :param indicator: choice of {"今日", "3日", "5日", "10日"}
    :type indicator: str
    :return: 指定 indicator 资金流向排行
    :rtype: pandas.DataFrame
    """
    indicator_map = {
        "今日": [
            "f62",
            "f12,f14,f2,f3,f62,f184,f66,f69,f72,f75,f78,f81,f84,f87,f204,f205,f124",
        ],
        "3日": [
            "f267",
            "f12,f14,f2,f127,f267,f268,f269,f270,f271,f272,f273,f274,f275,f276,f257,f258,f124",
        ],
        "5日": [
            "f164",
            "f12,f14,f2,f109,f164,f165,f166,f167,f168,f169,f170,f171,f172,f173,f257,f258,f124",
        ],
        "10日": [
            "f174",
            "f12,f14,f2,f160,f174,f175,f176,f177,f178,f179,f180,f181,f182,f183,f260,f261,f124",
        ],
    }
    url = "https://push2.eastmoney.com/api/qt/clist/get"
    # 正序100条
    params = {
        "fid": indicator_map[indicator][0],
        "po": "1",
        "pz": "100",
        "pn": "1",
        "np": "1",
        "fltt": "2",
        "invt": "2",
        "ut": "b2884a393a59ad64002292a3e90d46a5",
        "fs": "m:0+t:6+f:!2,m:0+t:13+f:!2,m:0+t:80+f:!2,m:1+t:2+f:!2,m:1+t:23+f:!2,m:0+t:7+f:!2,m:1+t:3+f:!2",
        "fields": indicator_map[indicator][1],
    }

    temp_list = []

    r = requests.get(url, params=params, timeout=15)
    data_json = r.json()
    inner_temp_df = pd.DataFrame(data_json["data"]["diff"])
    temp_list.append(inner_temp_df)

    # 倒序100条
    params = {
        "fid": indicator_map[indicator][0],
        "po": "0",
        "pz": "100",
        "pn": "1",
        "np": "1",
        "fltt": "2",
        "invt": "2",
        "ut": "b2884a393a59ad64002292a3e90d46a5",
        "fs": "m:0+t:6+f:!2,m:0+t:13+f:!2,m:0+t:80+f:!2,m:1+t:2+f:!2,m:1+t:23+f:!2,m:0+t:7+f:!2,m:1+t:3+f:!2",
        "fields": indicator_map[indicator][1],
    }

    r = requests.get(url, params=params, timeout=15)
    data_json = r.json()
    inner_temp_df = pd.DataFrame(data_json["data"]["diff"])
    temp_list.append(inner_temp_df)

    temp_df = pd.concat(temp_list, ignore_index=True)
    temp_df.reset_index(inplace=True)
    temp_df["index"] = range(1, len(temp_df) + 1)
    if indicator == "今日":
        temp_df.columns = [
            "序号",
            "最新价",
            "今日涨跌幅",
            "代码",
            "名称",
            "今日主力净流入-净额",
            "今日超大单净流入-净额",
            "今日超大单净流入-净占比",
            "今日大单净流入-净额",
            "今日大单净流入-净占比",
            "今日中单净流入-净额",
            "今日中单净流入-净占比",
            "今日小单净流入-净额",
            "今日小单净流入-净占比",
            "_",
            "今日主力净流入-净占比",
            "_",
            "_",
            "_",
        ]
        temp_df = temp_df[
            [
                "序号",
                "代码",
                "名称",
                "最新价",
                "今日涨跌幅",
                "今日主力净流入-净额",
                "今日主力净流入-净占比",
                "今日超大单净流入-净额",
                "今日超大单净流入-净占比",
                "今日大单净流入-净额",
                "今日大单净流入-净占比",
                "今日中单净流入-净额",
                "今日中单净流入-净占比",
                "今日小单净流入-净额",
                "今日小单净流入-净占比",
            ]
        ]
    elif indicator == "3日":
        temp_df.columns = [
            "序号",
            "最新价",
            "代码",
            "名称",
            "_",
            "3日涨跌幅",
            "_",
            "_",
            "_",
            "3日主力净流入-净额",
            "3日主力净流入-净占比",
            "3日超大单净流入-净额",
            "3日超大单净流入-净占比",
            "3日大单净流入-净额",
            "3日大单净流入-净占比",
            "3日中单净流入-净额",
            "3日中单净流入-净占比",
            "3日小单净流入-净额",
            "3日小单净流入-净占比",
        ]
        temp_df = temp_df[
            [
                "序号",
                "代码",
                "名称",
                "最新价",
                "3日涨跌幅",
                "3日主力净流入-净额",
                "3日主力净流入-净占比",
                "3日超大单净流入-净额",
                "3日超大单净流入-净占比",
                "3日大单净流入-净额",
                "3日大单净流入-净占比",
                "3日中单净流入-净额",
                "3日中单净流入-净占比",
                "3日小单净流入-净额",
                "3日小单净流入-净占比",
            ]
        ]
    elif indicator == "5日":
        temp_df.columns = [
            "序号",
            "最新价",
            "代码",
            "名称",
            "5日涨跌幅",
            "_",
            "5日主力净流入-净额",
            "5日主力净流入-净占比",
            "5日超大单净流入-净额",
            "5日超大单净流入-净占比",
            "5日大单净流入-净额",
            "5日大单净流入-净占比",
            "5日中单净流入-净额",
            "5日中单净流入-净占比",
            "5日小单净流入-净额",
            "5日小单净流入-净占比",
            "_",
            "_",
            "_",
        ]
        temp_df = temp_df[
            [
                "序号",
                "代码",
                "名称",
                "最新价",
                "5日涨跌幅",
                "5日主力净流入-净额",
                "5日主力净流入-净占比",
                "5日超大单净流入-净额",
                "5日超大单净流入-净占比",
                "5日大单净流入-净额",
                "5日大单净流入-净占比",
                "5日中单净流入-净额",
                "5日中单净流入-净占比",
                "5日小单净流入-净额",
                "5日小单净流入-净占比",
            ]
        ]
    elif indicator == "10日":
        temp_df.columns = [
            "序号",
            "最新价",
            "代码",
            "名称",
            "_",
            "10日涨跌幅",
            "10日主力净流入-净额",
            "10日主力净流入-净占比",
            "10日超大单净流入-净额",
            "10日超大单净流入-净占比",
            "10日大单净流入-净额",
            "10日大单净流入-净占比",
            "10日中单净流入-净额",
            "10日中单净流入-净占比",
            "10日小单净流入-净额",
            "10日小单净流入-净占比",
            "_",
            "_",
            "_",
        ]
        temp_df = temp_df[
            [
                "序号",
                "代码",
                "名称",
                "最新价",
                "10日涨跌幅",
                "10日主力净流入-净额",
                "10日主力净流入-净占比",
                "10日超大单净流入-净额",
                "10日超大单净流入-净占比",
                "10日大单净流入-净额",
                "10日大单净流入-净占比",
                "10日中单净流入-净额",
                "10日中单净流入-净占比",
                "10日小单净流入-净额",
                "10日小单净流入-净占比",
            ]
        ]
    return temp_df
def get_stock_sectors(stock_codes, skip_db_query=False, db_config=None):
    """
    从数据库查询股票的板块信息
    参数:
        stock_codes: 股票代码列表
        skip_db_query: 是否跳过数据库查询，默认为False
        db_config: 数据库连接配置，如果为None则使用默认配置
    返回:
        字典，键为股票代码，值为对应的板块名称
    """
    if not stock_codes:
        print("没有股票代码，跳过数据库查询")
        return {}

    if skip_db_query:
        print("根据设置跳过数据库查询")
        return {}

    # 数据库连接参数
    default_db_config = {
        'host': '175.178.5.14',
        'port': 33066,
        'user': 'root',
        'password': '07M@Y0sqL1',
        'database': 'stock',  # 假设数据库名为stock，如果不是，请修改
        'charset': 'utf8mb4',
        'connect_timeout': 10  # 添加连接超时设置
    }

    # 如果提供了自定义配置，则使用自定义配置
    # if db_config:
    #     for key, value in db_config.items():
    #         if value:  # 只更新非空值
    #             default_db_config[key] = value

    db_config = default_db_config

    # 构建SQL查询中的IN子句
    codes_str = ', '.join([f"'{code}'" for code in stock_codes])

    # 构建完整的SQL查询
    sql = f"""
    select
        spld.symbol,
        s.SECTOR_NAME as '行业板块'
    from
        stock_personal_latest_data spld
        left join stock_sector_personal ssp on spld.ID=ssp.PERSONAL_ID
        left join stock_sector_last_data s on ssp.SECTOR_ID=s.ID
    where
        SYMBOL in ({codes_str})
        and VOLUME !='0'
        and s.SECTOR_TYPE ='2'
    order by field(spld.symbol,{codes_str})
    """

    print(f"执行SQL查询: {sql}")

    # 连接数据库并执行查询
    sectors = {}
    try:
        print("尝试连接数据库...")
        conn = pymysql.connect(**db_config)
        print("数据库连接成功")

        with conn.cursor() as cursor:
            print("执行SQL查询...")
            cursor.execute(sql)
            results = cursor.fetchall()
            print(f"查询结果: {len(results)} 条记录")
            
            # 打印查询结果示例
            if results:
                print("查询结果示例(前5条):")
                for i, (symbol, sector_name) in enumerate(results[:5]):
                    print(f"  {i+1}. {symbol}: {sector_name}")

            for symbol, sector_name in results:
                sectors[symbol] = sector_name
                print(f"股票 {symbol} 的板块: {sector_name}")
    except pymysql.err.OperationalError as e:
        print(f"数据库连接失败: {e}")
        print("将继续处理数据，但不包含板块信息")
    except Exception as e:
        print(f"数据库查询失败: {e}")
        print("将继续处理数据，但不包含板块信息")
    finally:
        if 'conn' in locals() and conn:
            conn.close()
            print("数据库连接已关闭")

    return sectors

def get_akshare_data(indicator="今日", type="1", max_retries=3, timeout=60):
    """
    从akshare API获取股票个股资金流排行数据，添加重试机制和超时控制
    参数:
        indicator: 指标，默认为"今日"
        max_retries: 最大重试次数，默认为3
        timeout: 超时时间（秒），默认为60
    返回:
        处理后的数据列表
    """
    import time
    import traceback
    
    for retry in range(max_retries):
        try:
            print(f"正在从akshare获取个股资金流排行数据，指标: {indicator}...（尝试 {retry+1}/{max_retries}）")
            
            # 设置超时时间
            start_time = time.time()
            
            # 获取akshare数据
            if type == "1":
                print("东财获取")
                stock_df = stock_individual_fund_flow_rank(indicator=indicator)
            elif type == "2":
                print("同花顺获取")
                stock_df = ak.stock_fund_flow_individual(symbol="即时")
            
            elapsed_time = time.time() - start_time
            print(f"API调用耗时: {elapsed_time:.2f}秒")
            
            # 检查返回数据
            if stock_df is None:
                print(f"API返回None，尝试重试...")
                continue
                
            if len(stock_df) == 0:
                print(f"API返回空DataFrame，尝试重试...")
                continue
                
            print(f"成功获取数据，共 {len(stock_df)} 条记录")
            print(f"数据列: {stock_df.columns.tolist()}")

            # 将DataFrame转换为字典列表
            data = stock_df.to_dict('records')

            processed_data = []
            stock_codes = []

            if type == "1":
                for item in data:
                    processed_item = {}

                    # 收集股票代码
                    if '代码' in item and item['代码']:
                        processed_item['代码'] = item['代码']
                        stock_codes.append(item['代码'])

                    # 筛选并重命名需要的字段
                    if '名称' in item:
                        processed_item['名称'] = item['名称']
                    if '最新价' in item:
                        processed_item['最新价'] = item['最新价']
                    if '涨跌幅' in item:
                        processed_item['今日涨跌幅'] = f"{item['涨跌幅']}% "
                    elif '今日涨跌幅' in item:
                        # 如果已经有今日涨跌幅字段，直接使用
                        if not str(item['今日涨跌幅']).endswith('%'):
                            processed_item['今日涨跌幅'] = f"{item['今日涨跌幅']}% "
                        else:
                            processed_item['今日涨跌幅'] = item['今日涨跌幅']

                    # 处理净流入字段
                    主力净流入 = 0

                    if '主力净流入-净额' in item and isinstance(item['主力净流入-净额'], (int, float)):
                        主力净流入 += item['主力净流入-净额']
                    elif '今日主力净流入-净额' in item and isinstance(item['今日主力净流入-净额'], (int, float)):
                        主力净流入 += item['今日主力净流入-净额']

                    if 主力净流入 != 0:
                        processed_item['主力净流入'] = round(主力净流入 / 100000000, 2)  # 转换为数值

                    else:
                        processed_item['主力净流入'] = 0.00  # 确保即使为0也添加该字段

                    #排序 主力净流入 从大到小 主力净流入小于0的,绝对值越大排的越前
                    processed_data.sort(key=lambda x: x['主力净流入'], reverse=True)

                    processed_data.append(processed_item)
            elif type == "2":
                for item in data:
                    processed_item = {}

                    # 收集股票代码
                    if '股票代码' in item and item['股票代码']:
                        stock_codes.append(item['股票代码'])

                    # 筛选并重命名需要的字段
                    if '股票简称' in item:
                        processed_item['股票简称'] = item['股票简称']
                    if '最新价' in item:
                        processed_item['最新价'] = item['最新价']
                    if '涨跌幅' in item:
                        processed_item['今日涨跌幅'] = f"{item['涨跌幅']}% "
                    elif '今日涨跌幅' in item:
                        # 如果已经有今日涨跌幅字段，直接使用
                        if not str(item['今日涨跌幅']).endswith('%'):
                            processed_item['今日涨跌幅'] = f"{item['今日涨跌幅']}% "
                        else:
                            processed_item['今日涨跌幅'] = item['今日涨跌幅']

                    # 处理净流入字段
                    主力净流入 = 0
                    主力净流入 = item['净额']
                    # 判断主力净流入最后结尾是什么单位 如果是万 则转换为亿 并保留2位小数
                    if 主力净流入.endswith("万"):
                        # 去掉中文单位"万" 并转换为亿 并保留2位小数
                        主力净流入 = round(float(主力净流入[:-1]) / 10000, 2)
                        processed_item['主力净流入'] = 主力净流入
                    elif 主力净流入.endswith("亿"):
                        主力净流入 = float(主力净流入[:-1])
                        processed_item['主力净流入'] = 主力净流入
                    # 排序 主力净流入 从大到小 主力净流入小于0的,绝对值越大排的越前
                    # processed_data.sort(key=lambda x: x['主力净流入'], reverse=True)

                    processed_data.append(processed_item)

            return processed_data, stock_codes
            
        except Exception as e:
            print(f"获取akshare数据失败 (尝试 {retry+1}/{max_retries}): {e}")
            print("详细错误信息:")
            traceback.print_exc()
            
            if retry < max_retries - 1:
                wait_time = 2 ** retry  # 指数退避策略
                print(f"等待 {wait_time} 秒后重试...")
                time.sleep(wait_time)
            else:
                print("已达到最大重试次数，尝试使用备选数据源...")
                return get_fallback_data(indicator)
    
    return [], []

def get_fallback_data(indicator="今日"):
    """
    当AKShare API调用失败时，提供备选数据源
    参数:
        indicator: 指标，默认为"今日"
    返回:
        处理后的数据列表
    """
    try:
        print("使用备选数据源...")
        
        # 尝试使用其他AKShare API获取相关数据
        try:
            print("尝试获取A股实时行情数据...")
            stock_df = ak.stock_zh_a_spot()
            
            if stock_df is not None and len(stock_df) > 0:
                print(f"成功获取A股实时行情数据，共 {len(stock_df)} 条记录")
                
                # 将DataFrame转换为字典列表
                data = stock_df.to_dict('records')
                
                processed_data = []
                stock_codes = []
                
                for item in data:
                    processed_item = {}
                    
                    # 收集股票代码
                    if '代码' in item and item['代码']:
                        stock_codes.append(item['代码'])
                    
                    # 筛选并重命名需要的字段
                    if '名称' in item:
                        processed_item['名称'] = item['名称']
                    if '最新价' in item:
                        processed_item['最新价'] = item['最新价']
                    if '涨跌幅' in item:
                        processed_item['今日涨跌幅'] = f"{item['涨跌幅']}% "
                    
                    # 由于没有主力净流入数据，添加占位符
                    processed_item['主力净流入'] = "数据暂缺"
                    
                    processed_data.append(processed_item)
                
                print("使用A股实时行情数据作为备选")
                return processed_data, stock_codes
        except Exception as e:
            print(f"获取A股实时行情数据失败: {e}")
        
        # 如果所有API都失败，返回示例数据
        print("所有API调用失败，使用示例数据")
        
        # 创建示例数据
        example_data = [
            {"名称": "示例股票1", "最新价": 10.5, "今日涨跌幅": "2.5%", "主力净流入": "1.2亿"},
            {"名称": "示例股票2", "最新价": 15.8, "今日涨跌幅": "-1.3%", "主力净流入": "-0.8亿"},
            {"名称": "示例股票3", "最新价": 25.2, "今日涨跌幅": "3.7%", "主力净流入": "2.5亿"},
            {"名称": "示例股票4", "最新价": 8.6, "今日涨跌幅": "-2.1%", "主力净流入": "-1.5亿"},
            {"名称": "示例股票5", "最新价": 32.1, "今日涨跌幅": "0.5%", "主力净流入": "0.3亿"}
        ]
        
        example_codes = ["000001", "000002", "000003", "000004", "000005"]
        
        print("使用示例数据作为备选，共5条记录")
        return example_data, example_codes
        
    except Exception as e:
        print(f"获取备选数据失败: {e}")
        return [], []

def json_to_excel(json_file, excel_output=None):
    """
    将JSON文件转换为Excel文件
    参数:
        json_file: JSON文件路径
        excel_output: 输出的Excel文件路径（可选）
    返回:
        Excel文件路径
    """
    if not excel_output:
        excel_output = json_file.replace('.json', '.xlsx')

    try:
        # 读取JSON文件
        with open(json_file, 'r', encoding='utf-8') as f:
            data = json.load(f)

        # 创建DataFrame
        df = pd.DataFrame(data)

        # 写入Excel文件并设置格式
        with ExcelWriter(excel_output, engine='openpyxl') as writer:
            # 如果数据量小于等于20行，只创建一个sheet
            if len(df) <= 20:
                df.to_excel(writer, index=False, sheet_name='Sheet1')

                # 获取工作表
                worksheet = writer.sheets['Sheet1']

                # 设置所有列宽为4cm（约18个字符宽度）
                for column in worksheet.columns:
                    column_letter = openpyxl.utils.get_column_letter(column[0].column)
                    worksheet.column_dimensions[column_letter].width = 18

                # 设置所有行高为40
                for i in range(1, worksheet.max_row + 1):
                    worksheet.row_dimensions[i].height = 40

                # 设置字体和对齐方式
                font = Font(name='微软雅黑')
                #字体大小设为14
                font.size = 14
                alignment = Alignment(horizontal='center', vertical='center')

                # 创建黄色填充样式（用于表头）
                yellow_fill = PatternFill(start_color='FFFF00', end_color='FFFF00', fill_type='solid')

                # 创建边框样式
                thin_border = Border(
                    left=Side(style='thin'),
                    right=Side(style='thin'),
                    top=Side(style='thin'),
                    bottom=Side(style='thin')
                )

                # 获取列索引
                headers = list(df.columns)
                涨跌幅_idx = headers.index('今日涨跌幅') + 1 if '今日涨跌幅' in headers else -1
                净流入_idx = headers.index('主力净流入') + 1 if '主力净流入' in headers else -1

                # 应用格式到所有单元格
                for row_idx, row in enumerate(worksheet.iter_rows()):
                    for cell_idx, cell in enumerate(row):
                        # 基本格式设置
                        cell.alignment = alignment
                        cell.border = thin_border  # 应用边框

                        #字体大小设为14
                        cell.font.size = 14
                        # 为第一行（表头）设置黄色背景和默认字体
                        if row_idx == 0:
                            cell.fill = yellow_fill
                            cell.font = font
                        else:
                            # 处理涨跌幅列的条件格式
                            if 涨跌幅_idx > 0 and cell_idx + 1 == 涨跌幅_idx:
                                # 提取数值部分（去掉%符号）
                                value_str = str(cell.value).replace('%', '') if cell.value else '0'
                                try:
                                    value = float(value_str)
                                    # 根据值设置字体颜色和大小
                                    if value < 0:
                                        cell.font = Font(name='微软雅黑', color='00B050', size=14)  # 添加size参数
                                    else:
                                        cell.font = Font(name='微软雅黑', color='FF0000', size=14)  # 添加size参数
                                except ValueError:
                                    cell.font = Font(name='微软雅黑', size=14)  # 添加默认size


                            # 处理主力净流入列的条件格式
                            elif 净流入_idx > 0 and cell_idx + 1 == 净流入_idx:
                                # 提取数值部分（去掉"亿"字并转换为数字）
                                value_str = str(cell.value).replace('亿', '') if cell.value else '0'
                                try:
                                    value = float(value_str)
                                    # 根据值设置字体颜色和大小
                                    if value < 0:
                                        cell.font = Font(name='微软雅黑', color='00B050', size=14)  # 添加size参数
                                    else:
                                        cell.font = Font(name='微软雅黑', color='FF0000', size=14)  # 添加size参数
                                except ValueError:
                                    cell.font = Font(name='微软雅黑', size=14)  # 添加默认size

            else:
                # 计算需要多少个sheet
                rows_per_sheet = 20
                total_rows = len(df)
                sheet_count = (total_rows + rows_per_sheet - 1) // rows_per_sheet  # 向上取整

                print(f"将数据分割为 {sheet_count} 个sheet页，每页最多 {rows_per_sheet} 行")

                # 获取列索引（用于所有sheet）
                headers = list(df.columns)
                涨跌幅_idx = headers.index('今日涨跌幅') + 1 if '今日涨跌幅' in headers else -1
                净流入_idx = headers.index('主力净流入') + 1 if '主力净流入' in headers else -1

                # 设置字体和对齐方式
                font = Font(name='微软雅黑')
                alignment = Alignment(horizontal='center', vertical='center')

                # 创建黄色填充样式（用于表头）
                yellow_fill = PatternFill(start_color='FFFF00', end_color='FFFF00', fill_type='solid')

                # 创建边框样式
                thin_border = Border(
                    left=Side(style='thin'),
                    right=Side(style='thin'),
                    top=Side(style='thin'),
                    bottom=Side(style='thin')
                )

                # 为每个sheet写入数据
                for sheet_idx in range(sheet_count):
                    start_row = sheet_idx * rows_per_sheet
                    end_row = min(start_row + rows_per_sheet, total_rows)

                    # 创建当前sheet的数据片段
                    sheet_df = df.iloc[start_row:end_row]

                    # 写入当前sheet
                    sheet_name = f'Sheet{sheet_idx + 1}'
                    sheet_df.to_excel(writer, index=False, sheet_name=sheet_name)

                    # 获取当前工作表
                    worksheet = writer.sheets[sheet_name]

                    # 设置所有列宽为4cm（约18个字符宽度）
                    for column in worksheet.columns:
                        column_letter = openpyxl.utils.get_column_letter(column[0].column)
                        worksheet.column_dimensions[column_letter].width = 18

                    # 设置所有行高为40
                    for i in range(1, worksheet.max_row + 1):
                        worksheet.row_dimensions[i].height = 40

                    # 应用格式到所有单元格
                    for row_idx, row in enumerate(worksheet.iter_rows()):
                        for cell_idx, cell in enumerate(row):
                            # 基本格式设置
                            cell.alignment = alignment
                            cell.border = thin_border  # 应用边框

                            # 为第一行（表头）设置黄色背景和默认字体
                            if row_idx == 0:
                                cell.fill = yellow_fill
                                cell.font = font
                            else:
                                # 处理涨跌幅列的条件格式
                                if 涨跌幅_idx > 0 and cell_idx + 1 == 涨跌幅_idx:
                                    # 提取数值部分（去掉%符号）
                                    value_str = str(cell.value).replace('%', '') if cell.value else '0'
                                    try:
                                        value = float(value_str)
                                        # 根据值设置字体颜色
                                        if value < 0:
                                            cell.font = Font(name='微软雅黑', color='00B050')  # 绿色
                                        else:
                                            cell.font = Font(name='微软雅黑', color='FF0000')  # 红色
                                    except ValueError:
                                        cell.font = font  # 如果无法转换为数字，使用默认字体

                                # 处理主力净流入列的条件格式
                                elif 净流入_idx > 0 and cell_idx + 1 == 净流入_idx:
                                    # 提取数值部分（去掉"亿"字并转换为数字）
                                    value_str = str(cell.value).replace('亿', '') if cell.value else '0'
                                    try:
                                        value = float(value_str)
                                        # 根据值设置字体颜色
                                        if value < 0:
                                            cell.font = Font(name='微软雅黑', color='00B050')  # 绿色
                                        else:
                                            cell.font = Font(name='微软雅黑', color='FF0000')  # 红色
                                    except ValueError:
                                        cell.font = font  # 如果无法转换为数字，使用默认字体
                                else:
                                    cell.font = font  # 其他列使用默认字体

        print(f"[成功] Excel文件已生成: {excel_output}")
        return excel_output

    except Exception as e:
        print(f"[失败] 转换失败: {e}")
        return None

def process_akshare_data(output_file=None, indicator="今日", type="1", skip_db_query=False, db_config=None, keep_all=False):
    """
    处理akshare API数据：获取数据，转换主力净流入单位为亿，并保存为JSON和Excel文件
    参数:
        output_file: 输出的JSON文件路径（可选）
        indicator: akshare API的指标参数，默认为"今日"
        skip_db_query: 是否跳过数据库查询，默认为False
        db_config: 数据库连接配置，如果为None则使用默认配置
        keep_all: 是否保留所有数据，默认为False（如果数据量大于200条，只保留前100和后100条）
    """

    # 按照主力净流入 主力净流入小于0的,绝对值越大排的越前


    # 设置默认输出文件名
    if not output_file:
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_file = f"json/akshare_stock_flow_{timestamp}.json"

    # 确保输出目录存在
    os.makedirs(os.path.dirname(output_file), exist_ok=True)

    # 设置Excel输出文件名
    excel_output = output_file.replace('.json', '.xlsx')

    try:
        # 从akshare获取数据
        processed_data, stock_codes = get_akshare_data(indicator, type)
        print(processed_data)



        # 查询股票板块信息
        print(f"正在查询 {len(stock_codes)} 只股票的板块信息...")
        sectors = get_stock_sectors(stock_codes, False, db_config)
        print(f"查询到 {len(sectors)} 只股票的板块信息")

        # 将板块信息添加到处理后的数据中
        # print("开始匹配行业板块信息...")
        matched_count = 0
        
        for i, item in enumerate(processed_data):

            if item['代码'] and item['代码'] in sectors:
                item['行业板块'] = sectors[item['代码']]
                matched_count += 1
                # print(f"匹配成功: {stock_code} -> {sectors[stock_code]}")
            else:
                item['行业板块'] = '未知板块'
                # print(f"匹配失败: {stock_code}")
        
        print(f"行业板块匹配完成: 共匹配 {matched_count}/{len(processed_data)} 只股票")



        if len(processed_data) > 200 and not keep_all:
            print(f"数据量较大 ({len(processed_data)} 条)，根据设置只保留前100和后100条")
            processed_lastData = processed_data[-100:]
            processed_lastData.sort(key=lambda x: abs(x['主力净流入']), reverse=True)
            processed_data = processed_data[:100] + processed_lastData
        else:
            print(f"保留全部 {len(processed_data)} 条数据")

        # 主力净流入拼接'亿'
        for item in processed_data:
            item['主力净流入'] = str(item['主力净流入']) + '亿'
        # 今日涨跌幅拼接空白字符
        for item in processed_data:
            item['今日涨跌幅'] = str(item['今日涨跌幅']) + '\n'


        # 创建DataFrame
        df = pd.DataFrame(processed_data)
        # 删除代码列
        if '代码' in df.columns:
            df = df.drop('代码', axis=1)

        # 写入处理后的JSON文件
        # with open(output_file, 'w', encoding='utf-8') as f:
        #     json.dump(
        #         processed_data,
        #         f,
        #         ensure_ascii=False,
        #         indent=4,
        #         separators=(',', ': ')
        #     )

        # 写入Excel文件并设置格式
        with ExcelWriter(excel_output, engine='openpyxl') as writer:
            # 计算需要多少个sheet
            rows_per_sheet = 20
            total_rows = len(df)
            sheet_count = (total_rows + rows_per_sheet - 1) // rows_per_sheet  # 向上取整

            print(f"将数据分割为 {sheet_count} 个sheet页，每页最多 {rows_per_sheet} 行")

            # 如果没有数据，至少创建一个空sheet
            if sheet_count == 0:
                sheet_count = 1

            # 获取列索引（用于所有sheet）
            headers = list(df.columns)
            涨跌幅_idx = headers.index('今日涨跌幅') + 1 if '今日涨跌幅' in headers else -1
            净流入_idx = headers.index('主力净流入') + 1 if '主力净流入' in headers else -1

            # 设置字体和对齐方式
            font = Font(name='微软雅黑', size=14)  # 在此处直接设置size
            alignment = Alignment(horizontal='center', vertical='center')

            #字体大小设为14
            font.size = 14
            # 创建黄色填充样式（用于表头）
            yellow_fill = PatternFill(start_color='FFFF00', end_color='FFFF00', fill_type='solid')

            # 创建边框样式
            thin_border = Border(
                left=Side(style='thin'),
                right=Side(style='thin'),
                top=Side(style='thin'),
                bottom=Side(style='thin')
            )

            # 为每个sheet写入数据
            for sheet_idx in range(sheet_count):
                start_row = sheet_idx * rows_per_sheet
                end_row = min(start_row + rows_per_sheet, total_rows)

                # 创建当前sheet的数据片段
                sheet_df = df.iloc[start_row:end_row]

                # 写入当前sheet
                sheet_name = f'Sheet{sheet_idx + 1}'
                sheet_df.to_excel(writer, index=False, sheet_name=sheet_name)

                # 获取当前工作表
                worksheet = writer.sheets[sheet_name]

                # 设置所有列宽为4cm（约18个字符宽度）
                for column in worksheet.columns:
                    column_letter = openpyxl.utils.get_column_letter(column[0].column)
                    worksheet.column_dimensions[column_letter].width = 18

                # 设置所有行高为40
                for i in range(1, worksheet.max_row + 1):
                    worksheet.row_dimensions[i].height = 40

                # 应用格式到所有单元格
                for row_idx, row in enumerate(worksheet.iter_rows()):
                    for cell_idx, cell in enumerate(row):
                        # 基本格式设置
                        cell.alignment = alignment
                        cell.border = thin_border  # 应用边框

                        # 为第一行（表头）设置黄色背景和默认字体
                        if row_idx == 0:
                            cell.fill = yellow_fill
                            cell.font = font
                        else:
                            # 处理涨跌幅列的条件格式
                            if 涨跌幅_idx > 0 and cell_idx + 1 == 涨跌幅_idx:
                                # 提取数值部分（去掉%符号）
                                value_str = str(cell.value).replace('%', '') if cell.value else '0'
                                try:
                                    value = float(value_str)
                                    # 根据值设置字体颜色
                                    if value < 0:
                                        cell.font = Font(name='微软雅黑', color='00B050', size=14)  # 绿色
                                    else:
                                        cell.font = Font(name='微软雅黑', color='FF0000', size=14)  # 红色
                                except ValueError:
                                    cell.font = Font(name='微软雅黑', size=14)  # 如果无法转换为数字，使用默认字体

                            # 处理主力净流入列的条件格式
                            elif 净流入_idx > 0 and cell_idx + 1 == 净流入_idx:
                                # 提取数值部分（去掉"亿"字并转换为数字）
                                value_str = str(cell.value).replace('亿', '') if cell.value else '0'
                                try:
                                    value = float(value_str)
                                    # 根据值设置字体颜色
                                    if value < 0:
                                        cell.font = Font(name='微软雅黑', color='00B050', size=14)  # 绿色
                                    else:
                                        cell.font = Font(name='微软雅黑', color='FF0000', size=14)  # 红色
                                except ValueError:
                                    cell.font = Font(name='微软雅黑', size=14)  # 如果无法转换为数字，使用默认字体
                            else:
                                cell.font = font  # 其他列使用默认字体

        print(f"[成功] 处理完成: ")
        print(f"  - JSON文件: {output_file}")
        print(f"  - Excel文件: {excel_output}")

        return output_file, excel_output

    except Exception as e:
        print(f"[失败] 处理失败: {e}")
        return None, None

def excel_sheet_to_image(worksheet, output_path):
    """
    将Excel工作表转换为图片，支持中文字体
    参数:
        worksheet: openpyxl工作表对象
        output_path: 输出图片路径
    返回:
        图片路径
    """
    try:
        print(f"正在将工作表 '{worksheet.title}' 转换为图片...")

        # 设置中文字体支持
        import matplotlib
        # 尝试设置中文字体，如果失败则使用默认字体
        try:
            # 尝试使用微软雅黑字体
            matplotlib.rcParams['font.family'] = ['Microsoft YaHei', 'SimHei', 'sans-serif']
            print("已设置中文字体支持")
        except Exception as e:
            print(f"设置中文字体失败，将使用默认字体: {e}")
            # 如果没有中文字体，尝试使用系统默认字体
            matplotlib.rcParams['font.family'] = 'sans-serif'

        # 获取工作表的行数和列数
        max_row = worksheet.max_row
        max_col = worksheet.max_column

        # 创建一个表格数据
        data = []
        for row in worksheet.iter_rows(values_only=True):
            data.append(list(row))

        # 创建一个图表
        fig, ax = plt.subplots(figsize=(max_col * 2, max_row * 0.8))  # 根据表格大小调整图片大小

        # 隐藏坐标轴
        ax.axis('off')
        ax.axis('tight')

        # 创建表格
        table = ax.table(cellText=data,
                         loc='center',
                         cellLoc='center',
                         colWidths=[0.2] * max_col)

        # 设置表格样式
        table.auto_set_font_size(False)
        table.set_fontsize(12)
        table.scale(1, 3)  # 调整表格高度

        # 设置表头样式（第一行）
        for i in range(max_col):
            table[(0, i)].set_facecolor('#FFFF00')  # 黄色背景

        # 设置单元格样式
        for i in range(1, max_row):
            for j in range(max_col):
                cell_value = data[i][j] if i < len(data) and j < len(data[i]) else ""

                # 处理涨跌幅列
                if "%" in str(cell_value):
                    try:
                        value = float(str(cell_value).replace('%', ''))
                        if value < 0:
                            table[(i, j)].get_text().set_color('green')
                        else:
                            table[(i, j)].get_text().set_color('red')
                    except ValueError:
                        pass

                # 处理主力净流入列
                if "亿" in str(cell_value):
                    try:
                        value = float(str(cell_value).replace('亿', ''))
                        if value < 0:
                            table[(i, j)].get_text().set_color('green')
                        else:
                            table[(i, j)].get_text().set_color('red')
                    except ValueError:
                        pass

        # 调整布局
        plt.tight_layout()

        # 保存图片
        plt.savefig(output_path, dpi=150, bbox_inches='tight')
        plt.close(fig)

        print(f"图片已保存: {output_path}")
        return output_path

    except Exception as e:
        print(f"转换图片失败: {e}")
        import traceback
        traceback.print_exc()  # 打印详细错误信息
        return None

def main():
    """
    主函数：从akshare API获取数据并处理
    """
    try:
        # 获取年月日时分秒
        dayMonth = datetime.now().strftime("%m月%d号")
        time = datetime.now().strftime("%H点%M分")
        # 设置输出目录
        os.makedirs('../json', exist_ok=True)

        # 获取当前时间戳
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

        dateStamp = datetime.now().strftime("%Y%m%d")
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_dir = f"../spiltExcel/input/{dateStamp}"
        os.makedirs(output_dir, exist_ok=True)

        # 设置输出文件名
        output_file = f"{output_dir}/zjlx_{timestamp}.xlsx"

        # 处理akshare数据
        print("开始从akshare获取数据并处理...")
        json_file, excel_file = process_akshare_data(
            output_file=output_file,
            indicator="今日",
            type="1",
            skip_db_query=False,  # 启用数据库查询
            keep_all=False  # 只保留前100和后100条数据
        )

        if json_file and excel_file:
            print(f"处理完成！")
            print(f"JSON文件: {json_file}")
            print(f"Excel文件: {excel_file}")
            print("开始为Excel文件生成截图...")
            # 创建截图保存目录
            #判断是上午还是下午
            if datetime.now().hour < 12:
                day = '上午'
            else :
                day = '下午'
            screenshot_dir = f"../spiltExcel/output/{dateStamp}/zjlx/{day}"
            capture_excel_sheets_screenshots(
                excel_path=excel_file,
                output_dir=screenshot_dir,
                start_from=1  # 从第2个工作表开始截图（跳过"全量数据"表）
            )

            dayMonth = dayMonth.lstrip('0')
            #time的时间大于15点 则为下午
            if datetime.now().hour >= 15:
                print(f"主力流入及流出_盘后 {dayMonth}")
            else:
                print(f"主力流入及流出_{time} {dayMonth}")
            print("ps:数据仅供参考，不构成投资建议")
        else:
            print("处理失败！")

    except Exception as e:
        print(f"程序执行出错: {e}")
def process():
    main()

if __name__ == "__main__":
    main()